package org.andengine.shmup;

import java.util.ArrayList;

import org.anddev.andengine.entity.sprite.AnimatedSprite;
import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
import org.anddev.andengine.util.Debug;

import team2.game.crow.Laser;
import team2.game.crow.SpritePool;

import com.badlogic.gdx.math.Vector2;

public class Enemy extends AnimatedSprite{

	private String type = "GRUNT";
	private String name = "";
	
	private MotionType mt = MotionType.LINEAR;
	public boolean isAlive;
	
	protected int hp = 100;
	private float initX = 0.0f;
	private float initY = 0.0f;
	private float driftS =0, driftF =0, pFactor = .001f;
	private int shotCount = 0;
    
	protected static final int CAMERA_WIDTH = 480;
    protected static final int CAMERA_HEIGHT = 720;
    protected static final float DEFAULT_VEL = 60f;
	private static final float ENEMY_RECOVERY = 1.6f;
	private static final float ENEMY_GAP = .25f;
	public int maxShots = 3;
	protected ArrayList<Laser> bullets;
	protected boolean isGrunt = true, firing = false, drifting =false, isElite = false;
	protected SpritePool bulletPool;
	private Laser temp;
	
	protected Vector2 v = new Vector2(DEFAULT_VEL, DEFAULT_VEL);
	public float timeAlive = 0;
	public float def = 1;
	
	public Enemy(final float pX, final float pY, final TiledTextureRegion pTextureRegion) {
		super(pX, pY, pTextureRegion);
		this.initX = pX;
		this.initY = pY;
		this.reset();
        
	}
	
	public void setBulletPool(final SpritePool bulletpool){
		this.bulletPool = bulletpool;
	}
	
	public void setBulletArray(final ArrayList<Laser> bullets){
		this.bullets = bullets;
	}
	
	public void setDrift(float span, float freq){
		this.driftS = span;
		this.driftF = freq;
		this.drifting = true;
	}
	public void setDriftS(float span){
		this.setDrift(span, this.driftF);
	}
	public void setDriftF(float freq){
		this.setDrift(this.driftS, freq);
	}	
	public void setPFactor(float f)	{
		this.pFactor = f;
	}
	
	public void move(final float deltaTime) {
			//this.setDyDx();
			//switch(getT()){
			/*
				case ARC_POS:{ 
					if(dir_y == 0){
						v.y += 0.1*deltaTime;
					}
					else{
						if(dir_x == 0){
							v.x += 0.1*deltaTime;
						}
						else{
							v.y += 0.05*deltaTime;
						}
					}
					if(v.y!=0f){
						//this.setRotation((float)Math.toDegrees(Math.atan(v.x/v.y)));
					}
					break;
				}
				case ARC_NEG:{
					if(dir_y == 0){
						v.y -= 0.1*deltaTime;
					}
					else{
						if(dir_x == 0){
							v.x -= 0.1*deltaTime;
						}
						else{
							v.y -= 0.05*deltaTime;
						}
					}
					if(v.y!=0f){
						//this.setRotation((float)Math.toDegrees(Math.atan(v.x/v.y)));
					}
					break;
				}/*
				case LOOP:{
					delta2 = (initTime - System.nanoTime())/ 1000000000.0f - 10.0f;
					if(delta2 > 0.0 && delta2 <= 540){
						v.x = radius * (float)Math.cos(Math.toRadians(delta2*deltaTime)) *deltaTime;
						v.y = radius * -(float)Math.sin(Math.toRadians(delta2*deltaTime)) *deltaTime;
					}
					else{
						v.x = dir_x * (float)Math.abs(v.x);
						v.y = dir_y * (float)Math.abs(v.y);
					}
					if(v.y!=0f){
						//this.setRotation((float)Math.toDegrees(Math.atan(v.x/v.y)));
					}
					break;
				}
				default:{
					break;
				}
			}*/
			if(drifting)
				v.x = driftS*pFactor*(float)Math.cos(driftF*deltaTime);
			this.setPosition(this.getX() + (this.v.x*deltaTime),
								this.getY() + (this.v.y*deltaTime));
	}
	
	public void setVelocity(final float vx, final float vy){
		this.v.set(vx, vy);
	}
	
	public Vector2 getVelocity(){
		return this.v;
	}
	
	@Override
    protected void onManagedUpdate(final float pSecondsElapsed){
		this.isAlive = this.hp > 0;
		if(this.isAlive && this.isGrunt){
			this.move(pSecondsElapsed);
			if(onScreen()){ this.incTime(pSecondsElapsed); }
			else{ 
				if(timeAlive > 1.2*CAMERA_HEIGHT/(this.v.y) && !this.isElite)
						this.isAlive = false;
			}
			if(!this.type.equals("BLADER")){
				if(firing && this.timeAlive > (float)this.shotCount*ENEMY_GAP){ this.fire(); }
			}			
		}
		super.onManagedUpdate(pSecondsElapsed);
    }

	public float getInitX(){
		return this.initX;
	}
	public void setInitX(final float newX){
		this.initX = newX;
	}
	public float getInitY(){
		return this.initY;
	}
	public void setInitY(final float newY){
		this.initY = newY;
	}
	public void setT(final MotionType motionType){
		this.mt = motionType;
	}
	public MotionType getT() {
		return mt;
	}
	
	/* reset() now just resets the velocities, since obtainPoolItem will set the new
	 * initial positions anyways.
	 */	
	public void reset(){
		this.isAlive = true;
		this.firing = false;
		//dir_x = 0.0f;
		//dir_y = 0.0f;
		this.hp = 100;
		this.setVelocity(DEFAULT_VEL, DEFAULT_VEL);
	}
	public void setInitRotation(final float r){
		super.setRotation(r);
		//rotation = r;
		//this.setDyDx();
		this.setVelocity((float) Math.sin(Math.toRadians(r))*v.x,(float) Math.cos(Math.toRadians(r))*v.y);
	}
	/*
	@SuppressWarnings("unused")
	private void setDyDx(){
		dir_x = (float) Math.sin(this.getRotation());
		dir_y = (float) Math.cos(this.getRotation());
	}
	*/
	public void setType(final String type) {
		this.type = type;
	}

	public String getType() {
		return this.type;
	}

	public void setHP(final int hp) {
		this.hp -= hp;
		if(this.hp <= 0){
			this.isAlive = false;
		}
	}

	public float getCenterX(){
		return this.getX() + this.getWidth()/2;
	}
	
	public float getCenterY(){
		return this.getY() + this.getHeight()/2;
	}
	
	public int getHP() {
		return this.hp;
	}
	/*
	public void checkShotBounds(){
		
		for(Laser shot: bullets){
			if (shot.getY() > CAMERA_HEIGHT + 20){
				bulletPool.recyclePoolItem(shot);
				shotsToRemove.add(shot);
			}
		}
		bullets.removeAll(shotsToRemove);
		shotsToRemove.clear();
		
	}
	*/
	public void incTime(float delta){
		timeAlive += delta;
		if((firing && timeAlive > ENEMY_GAP*maxShots) || (!firing && timeAlive > ENEMY_RECOVERY)){
			timeAlive = 0;
			firing = !firing;
		}
	}
	
	private void fire(){
		Debug.d(this.name + " fired a shot");
		temp = bulletPool.obtainPoolItem(); 
		temp.setPosition(this.getCenterX(),this.getCenterY());
		temp.setDirection(-1);
		if(!temp.hasParent())
			this.getParent().attachChild(temp);
		
		this.bullets.add(temp);
		this.shotCount= (this.shotCount+1)%maxShots;
	}
	private boolean onScreen(){
		return this.getCenterX() >= 0 && this.getCenterY() >=0
			&& this.getCenterX() <= CAMERA_WIDTH && this.getCenterY() <= CAMERA_HEIGHT;
	}
	
	public void setName(final String name) {
		this.name = name;
	}

	public String getName() {
		return this.name;
	}
}